/** Provide common functionality to 2 dimensional array.*/
#ifndef _YARRAY2D_H
#define _YARRAY2D_H
#include <tool/ydefine.h>

/** Function pointers struct, use externally */
typedef struct array2D *array2D;
/** Data struct, use internally */
typedef struct array2DData *array2DData;

/** Struct of 2 dimensional array function pointers */
struct array2D {
  /*--- data ---*/
  array2DData d;
  /*--- function pointers ---*/
  /** Free a <code>array2D</code>, free up the memory.
  @param objP pass in the address of <code>array2D</code> to be free.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*free)(array2D *objP);
  /* specific operation */
  /** Free a 2 dimension array, free up the memory.
  @param array pass in the 2D array to be free.
  @param arrayLen the length of the 1st dimension of the <code>array</code>.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*free2DArray)(void **array, size_t arrayLen);
  /** Assign elements into this 2D array wrapper.
  <p>Provide a function to compare two objects of type <code>void *</code>.
  The function is of the form 
  <code>g_reply (*compare)(const void *, const void *)</code>.
  </p>
  <p>This function will be used for comparing a given object against 
  another object currently pointing to within in the array.
  <br/><code>anObject1</code> is the given object.
  <br/><code>anObject2</code> is the current object within the array.
  </p>
  <p><code>compare</code> should return <code>g_replyEqual</code> 
  if <code>anObject1</code> and <code>anObject2</code> are equal.
  Returns <code>g_replyLesser</code> or <code>g_replyGreater</code> 
  if <code>anObject1</code> is less than or greater than 
  <code>anObject2</code> respectively.
  </p>
  <p>This is a customized function provided by the object's library 
  and is NOT compulsory.
  </p>
  @param obj the 2 dimensional array object.
  @param a2DArray the 2 dimensional array.
  @param len the 1 dimension length of the 2 dimensional array.
  @param compare the function to compare 
    two objects of type <code>void *</code>.
  @return a newly created array wrapper, 
    or <code>NULL</code> if failure.
  */
  boolean (*assign)(array2D obj, 
      void **a2DArray, const size_t len,
      g_reply (*compare)(const void *anObj1, const void *anObj2));
  /** Removes reference to all assignable elements 
  within <code>array2D</code>. 
  Function does NOT free memory of the 2 dimension array.
  @param obj the 2 dimensional array object.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*clear)(array2D obj);
  /** find a position within the 2 dimension array that match this object.
  Will use the function that 
  compare two objects of type <code>void *</code>.
  The function is of the form 
  <code>g_reply (*compare)(const void *, const void *)</code>.
  @param obj the 2 dimensional array object.
  @param anObject find this object in the array.
  @return the position within the 2 dimension array or -1 if failure.
  */
  int (*find)(const array2D obj, const void *anObject);
  /*--- provide customized function */
  /** Provide a function to compare two objects of type <code>void *</code>.
  The function is of the form 
  <code>g_reply (*compare)(const void *, const void *)</code>.
  <p>This function will be used for comparing a given object against 
  another object currently pointing to within in the array.
  <br/><code>anObject1</code> is the given object.
  <br/><code>anObject2</code> is the current object within the array.
  </p>
  <p><code>compare</code> should return <code>g_replyEqual</code> 
  if <code>anObject1</code> and <code>anObject2</code> are equal.
  Returns <code>g_replyLesser</code> or <code>g_replyGreater</code> 
  if <code>anObject1</code> is less than or greater than 
  <code>anObject2</code> respectively.
  </p>
  <p>This is a customized function provided by the object's library 
  and is NOT compulsory.
  </p>
  @param obj the 2 dimensional array object.
  @param compare the function to compare 
    two objects of type <code>void *</code>.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*setFnCompare)(array2D obj, 
      g_reply (*compare)(const void *anObj1, const void *anObj2));
};

/** Create an empty array wrapper for the 2D array.
@return a newly created array wrapper, 
  or <code>NULL</code> if failure.
*/
array2D yarray2D_create(void);

/** Create an array wrapper for the 2D array, 
with an 2 dimensional array inside.
<p>Provide a function to compare two objects of type <code>void *</code>.
The function is of the form 
<code>g_reply (*compare)(const void *, const void *)</code>.
</p>
<p>This function will be used for comparing a given object against 
another object currently pointing to within in the array.
<br/><code>anObject1</code> is the given object.
<br/><code>anObject2</code> is the current object within the array.
</p>
<p><code>compare</code> should return <code>g_replyEqual</code> 
if <code>anObject1</code> and <code>anObject2</code> are equal.
Returns <code>g_replyLesser</code> or <code>g_replyGreater</code> 
if <code>anObject1</code> is less than or greater than 
<code>anObject2</code> respectively.
</p>
<p>This is a customized function provided by the object's library 
and is NOT compulsory.
</p>
@param a2DArray the 2 dimensional array.
@param len the 1 dimension length of the 2 dimensional array.
@param compare the function to compare 
  two objects of type <code>void *</code>.
@return a newly created array wrapper, 
  or <code>NULL</code> if failure.
*/
array2D yarray2D_createWith(void **a2DArray, const size_t len,
    g_reply (*compare)(const void *anObj1, const void *anObj2));

#endif /* _YARRAY2D_H */
